/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: a1227
 * Date: 2022-09-01
 * Time: 18:04
 */
class ListNode{
    //数值
    public int val;
    //前驱
    public ListNode prev;
    //后继
    public ListNode next;
    //构造方法
    public ListNode(int val){
        this.val = val;
    }
}

public class DoubleLinkedList {
    //傀儡节点-puppet的next即为头节点
    public ListNode puppet = new ListNode(-1);

    //尾节点
    public ListNode tail;

    //头插法
    public void addFirst(int data){
        ListNode newNode = new ListNode(data);
        //链表中一个元素都没有
        if(this.puppet.next == null){
            this.puppet.next = newNode;
            this.tail = newNode;
            return ;
        }
        //链表中至少有一个元素
        this.puppet.next.prev = newNode;
        newNode.next = this.puppet.next;
        this.puppet.next = newNode;
    }

    //尾插法
    public void addLast(int data){
        ListNode newNode = new ListNode(data);
        //链表中一个元素都没有
        if(this.puppet.next == null){
            this.puppet.next = newNode;
            this.tail = newNode;
            return ;
        }
        //链表中至少有一个元素
        this.tail.next = newNode;
        newNode.prev = this.tail;
        this.tail = newNode;
    }

    //寻找index位置的节点
    public ListNode searchIndex(int index){
        ListNode cur = this.puppet.next;
        while(index != 0){
            cur = cur.next;
            index--;
        }
        return cur;
    }

    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        ListNode newNode = new ListNode(data);
        //判断index的合法性
        if(index < 0 || index > size()){
            System.out.println("index位置不合法，请重新输入!");
            return ;
        }
        //index为0，即为头插
        if(index == 0){
            addFirst(data);
            return ;
        }
        //index为size()即为尾插
        if(index == size()){
            addLast(data);
            return ;
        }
        //其他位置
        ListNode cur = searchIndex(index);
        newNode.next = cur;
        cur.prev.next = newNode;
        newNode.prev = cur.prev;
        cur.prev = newNode;
    }

    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = this.puppet.next;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    //删除第一次出现关键字为key的节点
    public void remove(int key){
        if(this.puppet.next == null){
            System.out.println("链表为空，无法删除！");
            return ;
        }
        ListNode cur = this.puppet.next;
        while(cur != null){
            if(cur.val == key){
                //key所在节点是头节点
                if(cur == this.puppet.next){
                    //链表只有一个节点
                    if(cur.next == null){
                        this.puppet.next = null;
                        return ;
                    }
                    this.puppet.next = cur.next;
                    cur.next.prev = null;
                }else{
                    //key所在节点为中间节点
                    cur.prev.next = cur.next;
                    //key所在节点为尾节点
                    if(cur == this.tail){
                        this.tail = this.tail.prev;
                    }else{
                        cur.next.prev = cur.prev;
                    }
                }
                return ;
            }else{
                cur = cur.next;
            }
        }
    }

    //删除所有值为key的节点
    public void removeAllKey(int key){
        if(this.puppet.next == null){
            System.out.println("链表为空，无法删除！");
            return ;
        }
        ListNode cur = this.puppet.next;
        while(cur != null){
            if(cur.val == key){
                //key所在节点是头节点
                if(cur == this.puppet.next){
                    //链表只有一个节点
                    if(cur.next == null){
                        this.puppet.next = null;
                    }else {
                        this.puppet.next = cur.next;
                        cur.next.prev = null;
                    }
                }else{
                    //key所在节点为中间节点
                    cur.prev.next = cur.next;
                    //key所在节点为尾节点
                    if(cur == this.tail){
                        this.tail = this.tail.prev;
                    }else{
                        cur.next.prev = cur.prev;
                    }
                }
                cur = cur.next;
            }else{
                cur = cur.next;
            }
        }
    }

    //得到单链表的长度
    public int size(){
        ListNode cur = this.puppet.next;
        int count = 0;
        while(cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }

    //打印输出
    public void display(){
        if(this.puppet.next == null){
            System.out.println("链表为空，无法打印！");
            return ;
        }
        ListNode cur = this.puppet.next;
        while(cur != null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

    public void clear(){
        //暴力写法
        //this.puppet.next = null;
        //温柔写法
        ListNode cur = this.puppet.next;
        while(cur != null){
            ListNode curNext = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curNext;
        }
        this.tail = null;
        this.puppet.next = null;
    }
}
